#include "blockQueue.hpp"
#include "task.hpp"
#include <pthread.h>
#include <unistd.h>
#include <ctime>

void *consumer(void *args)
{
    BlockQueue<Task> *bq = static_cast<BlockQueue<Task> *>(args);
    while (true)
    {
         //sleep(1);//如果让消费慢点，而生产没加任何seep，让生产把阻塞队列打满
        //int data = 0; // 先定义一个

        Task t;
        // 1、将数据从blockqueue中获取--获取到了数据
        //bq->pop(&data); // 从阻塞队列里拿出来

        bq->pop(&t);
        t();//调用仿函数，void operator()()
        // 2、结合某种业务逻辑，处理数据 -- 暂时没有这个业务，后面说
        std::cout <<pthread_self()<< " ,consumer data: " <<t.formatArg()<< t.formatRes() << std::endl;
    }
}
void *productor(void *args)
{
    BlockQueue<Task> *bq = static_cast<BlockQueue<Task> *>(args);
    std::string opers = "+-*/%";
    while (true)
    {
         sleep(1);//让生产慢一点，就成了生产一个消费一个
        //  1、先通过某种渠道获取数据
        // int data = rand() % 10 + 1; // 生产1——10的数字

        int x = rand() % 20 + 1;
        int y = rand() % 10 + 1;
        char op = opers[rand() % opers.size()];
        // 2、将数据推送到blockqueue--完成生产过程
        // bq->push(data); // 将数据安全推送到阻塞队列里
        Task t(x, y, op);
        bq->push(t);
        std::cout <<pthread_self()<< " ,productor Task: " << t.formatArg()<<"?"<< std::endl;
    }
}
int main()
{
    srand((uint64_t)time(nullptr) ^ getpid()); //^getpid()使随机数字变得更随机一些
    // BlockQueue<int> *bq = new BlockQueue<int>(); // 两个线程看到的同一个队列
    BlockQueue<Task> *bq = new BlockQueue<Task>();

    // 单生产-单消费-> 多生产和多消费
    // pthread_t c, p;
    // pthread_create(&c, nullptr, consumer, bq);
    // pthread_create(&c, nullptr, productor, bq);

    //多生产和多消费
    pthread_t c[2], p[3];
    pthread_create(&c[0], nullptr, consumer, bq);
    pthread_create(&c[1], nullptr, consumer, bq);
    pthread_create(&p[0], nullptr, productor, bq);
    pthread_create(&p[1], nullptr, productor, bq);
    pthread_create(&p[2], nullptr, productor, bq);

    pthread_join(c[0], nullptr);
    pthread_join(c[1], nullptr);
    pthread_join(p[0], nullptr);
    pthread_join(p[1], nullptr);
    pthread_join(p[2], nullptr);
    delete bq;
    return 0;
}